package com.sensetime.jv.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@Slf4j
public class JsonUtils {

    public static final ObjectMapper objectMapper = new ObjectMapper();



    static {
        // 基础配置（保留原有配置）
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 忽略未知属性
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // 日期不序列化为时间戳
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null值
        objectMapper.findAndRegisterModules(); // 自动注册模块（如Java 8日期时间模块）

        // 新增配置
        // 序列化配置
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 空对象不报错
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT, false); // 不使用缩进
        objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true); // 使用枚举的toString方法

        // 反序列化配置
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); // 单值可以转为数组
        objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); // 空字符串转为null
        objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true); // 使用枚举的toString方法

        // 时间格式化配置
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 自定义日期时间格式
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        objectMapper.registerModule(javaTimeModule);

        // 处理数值精度问题
        objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
        objectMapper.configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, true);

        // 处理空字符串转数字的情况
        objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
    }

    private JsonUtils() {
        throw new UnsupportedOperationException("Utility class");
    }

    public static String writeValueAsString(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("Error converting object to JSON string", e);
        }
        return "";
    }


    /**
     * 将任意对象转换成指定类型的实例
     *
     * @param source 原始对象
     * @param clazz  目标类型
     * @param <T>    泛型
     * @return 转换后的对象；失败时返回 null
     */
    public static <T> T convertValue(Object source, Class<T> clazz) {
        if (source == null || clazz == null) {
            return null;
        }
        try {
            return objectMapper.convertValue(source, clazz);
        } catch (IllegalArgumentException e) {
            log.error("convert value error, source={}, clazz={}", source, clazz.getSimpleName(), e);
            return null;
        }
    }

    public static <T> T readValue(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            log.error("Error converting JSON string to object", e);
        }
        return null;
    }

    public static <T> List<T> readValueList(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz));
        } catch (JsonProcessingException e) {
            log.error("Error converting JSON string to List", e);
        }
        return null;
    }

    public static <K, V> Map<K, V> readValueMap(String json, Class<K> keyClass, Class<V> valueClass) {
        try {
            return objectMapper.readValue(json, objectMapper.getTypeFactory().constructMapType(Map.class, keyClass, valueClass));
        } catch (JsonProcessingException e) {
            log.error("Error converting JSON string to Map", e);
        }
        return null;
    }

    public static <T> T readValue(String json, TypeReference<T> typeReference) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            log.error("Error converting JSON string to type", e);
        }
        return null;
    }

    public static String toJsonPretty(Object object) {
        try {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.error("Error converting object to formatted JSON string", e);
        }
        return null;
    }

    public static void ignoreNullValues() {
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }
}
